One problem with the way indicated in Advanced Manipulate Functionality (linked by Bill Simpson) is that changing one of the tracked symbols in the body of the Manipulate triggers another update. For instance, if the x slider is moved in
Manipulate[If[y > x, y = x]; {x, y}, {x, 1, 10, 1}, {y, 1, x, 1}]
it triggers an update that cause the body of the Manipulate to be evaluated; if y > x, then setting y = x will trigger yet another update that basically has no effect. It just repeats the evaluation of the body without changing y since the condition y > x would now be false. If the rest of the body is more complicated than {x, y} and takes an appreciable amount of time to compute, then the performance might be sluggish.
Another way to go is to customize the control slightly:
Manipulate[
{x, y},
{{x, 1}, Manipulator[Dynamic[x, (x = #; y = Clip[y, {1, x}]) &], {1, 10, 1}] &},
{y, 1, x, 1}]
Here x and y are updated in the same command when the x slider is moved. This triggers an update of the Manipulate, but the evaluation of the body does not trigger a second update.