The accepted answer works well, but the idiom for a script re-invoking itself with sudo on demand can be simplified and made more portable:
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")"
Using [[ ... ]] instead of [ ... ] makes prepending x to the operands (or double-quoting the LHS) unnecessary.
Using bash -c instead of su -c to interpret the reconstructed command line makes the command more portable, because not all platforms support su -c (e.g., macOS doesn't).
In bash, $BASH_SOURCE is generally the more reliable way to refer to the running script.
With the above approach, any variable references or command / arithmetic substitutions in the arguments are invariably expanded by the calling shell.
If you instead you wanted delayed expansion - so that variable references aren't expanded until the sudo shell runs, in the context of the root user - use this:
(( __reinvoked )) || exec sudo -s __reinvoked=1 "$BASH_SOURCE" "$@"
Note that you'd then have to single-quote any arguments containing variable references or command substitutions for them to be delayed-expanded; e.g., '$USER'.
Note the use of ad-hoc environment variable __reinvoked to ensure re-invocation exactly once (even when initially already invoked as the root user).
Here's a sample script that demonstrates the first technique:
If not invoked as root, the script reinvokes itself with sudo -s, passing all arguments through as-is.
Unless previously authenticated and still within the timeout period, sudo will prompt for an administrator password.
#!/bin/bash
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")"
# Print the username and all arguments.
echo "Running as: $(id -un)"
echo "Arguments:"
for arg; do echo " $((++i)): [$arg]"; done
acfreitas's helpful answer demonstrates a "script-inside-a-script" technique where a here-document is used to provide shell code via stdin to sudo su.
Again, sudo -s is sufficient and quoting is important:
sudo -s -H <<'EOF'
echo "$HOME"
EOF
Note how the opening here-document delimiter, EOF in this case, is quoted in order to prevent the contents of the document from up-front interpretation by the current shell.
If you didn't quote (any part of) EOF, $HOME would be expand to the current user's home directory.
If you want to mix up-front and delayed expansion, leave the opening here-document delimiter unquoted and selectively \-quote $ instances:
sudo -s -H <<EOF
echo "Called by: $USER; root's home dir: \$HOME"
EOF