That is a really cool way of doing it. One adaptation for reuse that uses closures:
makeSearcher[xs_List] :=
Module[{lookup = Dispatch@Thread[xs -> True]},
Function[x, TrueQ@Replace[x, lookup]]]
test = Range@10000;
searcher = makeSearcher@test;
fast = searcher /@ test; // AbsoluteTiming
(* Out: {0.035002, Null} *)
slow = MemberQ[test, #] & /@ test; // AbsoluteTiming
(* Out: {9.002515, Null} *)
fast === slow
(* Out: True *)
Over 250x speed-up for an input list of 10k elements :-)
I've always been more comfortable with closures outside of Mathematica in more traditional functional languages like Lisp/Racket/et al. A colleague of mine wrote a neat little blog post a while back about closures in Mathematica:
http://searke.blogspot.com/2011/05/two-techniques-in-functional.html A very nice and neat exposition that inspires the above code.