One of the tricky things about bash and other Bourne-derived shells is that a condition used in an if or while statement is not an expression. It's a command, and the condition is treated as true or false depending on whether the command succeeded or failed. A command indicates success by returning an exit status of 0, and failure by returning anything else.
The built-in commands true and false do nothing other than returning an exit status denoting success or failure, respectively.
The [ ... ] and [[ ... ]] constructs can be used to simulate using an expression as a condition. [ is actually a command, very nearly equivalent to the test command.
If I need the equivalent of a Boolean variable in a bash script, I use a variable whose value is either the string true or the string false. If I use that variable as a condition, it expands to the command name true or false. I just have to be careful to ensure that such a variable never takes some value other than true or false.
And it's important to remember not to use the [ ... ] syntax. With a single argument, for example
if [ false ] ; then # This is incorrect!
the command succeeds because false is a non-empty string. Remember that the [ and ] are not part of the syntax of an if statement (though they're designed to look like they are).
An example:
#!/bin/bash
func() {
    if $1 ; then
        echo In func, the condition is true
    else
        echo In func, the condition is false
    fi
}
func false
func true
The output:
In func, the condition is false
In func, the condition is true
This technique does have some drawbacks. It can break if you assign a value other than exactly true or false to a variable, or even if you misspell the name of a variable. And unlike in languages with a built-in Boolean type and false and true literals, the shell is likely to fail to diagnose such errors, causing your script to silently misbehave.