The problem with mixing is that you need a way for the user to signal to the contract (or to the contract owner) the address they want to receive the ETH at after it is mixed.
If you have a trusted central party, and a secure communications channel, then you simply sign a message with the sender address, and ask for the mixer to forward to the receiver address.
If you want a trustless setup, one way is to use ring signatures. Basically you would have a mixing pool accepting a defined quantity of ETH by a certain number of senders. Once a defined number of deposits is reached, users can withdraw from a different address, by supplying a ring signature including all sender's public keys.
The ring signature proves that the user is the owner of one of the sender accounts, but does not provide any clue as to which one. Note that all users must send the same quantity of ETH.
These ring signatures can then be verified on-chain by a smart contract, but there is probably a cheaper way to handle this off-chain with some cryptoeconomics.
I believe there are examples of such ring signature verifiers available on GitHub