Is there a way to make a symbol behave as either mathord or mathrel depending on context?

No, a relation symbol will behave as such in all contexts and there is no “look back to see what came before me”. You could do a look forward for / to see whether what follows is a relation symbol and, in this case, treat it as an ordinary one. However this method has several limitations, because it would always require / (in math mode) to be followed by something still belonging to math mode.

The specific problem, quite common when dealing with equivalence relations, can be solved in a different way:

\newcommand{\quotient}[2]{#1/{#2}}

so that the call

$\quotient{X}{\sim}$

will do what you want and will also provide a good markup for possible improvement of the typesetting (a different slash, some spacing, whatever). The trick is bracing #2, so it will be a subformula and become an ordinary atom.

Here is a possible implementation of the “look forward”, which assumes that / will always be followed by something that should be considered as an ordinary atom:

\documentclass{article}
\usepackage{amsmath}

\newcommand{\qslash}[1]{\normalslash{#1}}
\mathchardef\normalslash=\mathcode`/
\begingroup\lccode`~=`/ \lowercase{\endgroup\let~}\qslash
\AtBeginDocument{\mathcode`/=\string"8000 }

\begin{document}

$X/\sim$

\end{document}

enter image description here

I don't recommend it.


Here's a LuaLaTeX-based solution, which sets up a Lua function which, by being assigned the to process_input_buffer callback, operates as a pre-processor, i.e., before TeX itself does any processing. The Lua function scans all input lines and encases all instances of \sim that are preceded by / (plus, possibly, some whitespace) in curly braces, "on the fly". Encasing a math atom in curly braces changes its status to "math-ordinary", which affects its spacing relative to adjacent math-atoms.

enter image description here

\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function slash_sim ( line )
  return ( string.gsub ( line , "/%s-\\sim", "/{\\sim}" ) )
end
luatexbase.add_to_callback ( "process_input_buffer", slash_sim, "slash_sim" )
\end{luacode}

\begin{document}
$x\sim y$ 

$U /\sim$   % no whitespace between "/" and "\sim"

$U / \sim$  % some whitespace between "/" and "\sim"

$U /{\sim}$ % status of "\sim" is set to math-ord manually 
\end{document}