Ranking a vector containing ties

list = {1, 2, 2, 3};

(Ordering@Ordering@# + Reverse@Ordering@Ordering@Reverse@#)/2 &@list

{1, 5/2, 5/2, 4}

As requested, here as a function:

rank[list_] := (Ordering@Ordering@list + Reverse@Ordering@Ordering@Reverse@list)/2

Both methods assume continuous sublists of identical elements, i.e., an already sorted vector. Gather is ~10x faster than Union for larger lists.

x = {1, 2, 2, 3};
f1[x_] := x /. (# -> Mean @ Flatten@Position[x, #] & /@ Union@x);
f2[x_] := 
  Module[{i = 1}, x /. ((First @ # -> (i + (i = i + Length @ #) - 1)/2) & /@ Gather@x)];

{f1@x, f2@x}
 {{1, 5/2, 5/2, 4}, {1, 5/2, 5/2, 4}}
y = Sort@RandomInteger[{0, 100}, {100000}];
AbsoluteTiming[r1 = f1@y;]
AbsoluteTiming[r2 = f2@y;]
r1 === r2
{2.090404, Null}
{0.327601, Null}
True